/**
 * \file LogManager.cpp
 * \brief LogManager declaration class
 * \author Edouard ROGE
 * \date 12 septembre 2010
 */

// to disable warnings from windows compilation
#define  _CRT_SECURE_NO_WARNINGS

#include <stdarg.h>
#include <stdio.h>
#include "Logger.h"
#include "LogManager.h"

namespace Core
{
	namespace Log
	{
		LogManager::LogManager() : m_iFlags(eLog_Info | eLog_Warning | eLog_Error | eLog_Assert)
		{
		}

		LogManager::~LogManager()
		{
		}

		void LogManager::AddLogger(Logger * _pLogger)
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			m_vpLogger.push_back(_pLogger);
		}

		void LogManager::RemoveLogger(Logger * _pLogger)
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			for (std::vector< Logger * >::iterator it = m_vpLogger.begin(); it != m_vpLogger.end();)
			{
				if ((*it) == _pLogger)
				{
					it = m_vpLogger.erase(it);
					continue;
				}
				++it;
			}
		}

		void LogManager::Write(const std::string & _filename, const int _nLine, const std::string & _function, const std::string & _strLog, const char * _fmt, ...)
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			std::string fullLog = /* time + */_strLog;
			va_list ap;
			va_start(ap, _fmt);

			char buf[256];
			vsprintf(buf, _fmt, ap);

			va_end(ap);

			fullLog += buf;
			fullLog += " at ";
			fullLog += _function;
			fullLog += " in ";
			fullLog += _filename;
			fullLog += ':';
			fullLog += std::to_string(_nLine);

			for (unsigned int iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
			{
				m_vpLogger[iLogger]->Write(fullLog);
			}
		}

		void LogManager::WriteLine(const std::string & _filename, const int _nLine, const std::string & _function, const std::string & _strLog, const char * _fmt, ...)
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			std::string fullLog = /* time + */_strLog;
			va_list ap;
			va_start(ap, _fmt);

			char buf[256];
			vsprintf(buf, _fmt, ap);

			va_end(ap);

			fullLog += buf;
			fullLog += " at ";
			fullLog += _function;
			fullLog += " in ";
			fullLog += _filename;
			fullLog += ':';
			fullLog += std::to_string(_nLine);
			fullLog += '\n';

			for (unsigned int iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
			{
				m_vpLogger[iLogger]->Write(fullLog);
			}
		}

		LogManager & LogManager::operator<<(int32 i)
		{
			char buf[64];
			sprintf(buf, "%d", i);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		LogManager & LogManager::operator<<(uint32 i)
		{
			char buf[64];
			sprintf(buf, "%d", i);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		LogManager & LogManager::operator<<(float f)
		{
			char buf[64];
			sprintf(buf, "%f", f);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		LogManager & LogManager::operator<<(double d)
		{
			char buf[64];
			sprintf(buf, "%f", d);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		LogManager & LogManager::operator<<(char c)
		{
			char buf[64];
			sprintf(buf, "%c", c);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		LogManager & LogManager::operator<<(const char * s)
		{
			if (s)
			{
				for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
					m_vpLogger[iLogger]->Write(s);
			}

			return (*this);
		}

		LogManager & LogManager::operator<<(char * s)
		{
			if (s)
			{
				for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
					m_vpLogger[iLogger]->Write(s);
			}

			return (*this);
		}

		LogManager & LogManager::operator<<(void * p)
		{
			char buf[64];
			sprintf(buf, "%p", p);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		LogManager & LogManager::operator<<(const void * p)
		{
			char buf[64];
			sprintf(buf, "%p", p);

			for (uint32 iLogger = 0; iLogger < m_vpLogger.size(); ++iLogger)
				m_vpLogger[iLogger]->Write(buf);

			return (*this);
		}

		void LogManager::AddFlags(uint32 _iFlags)
		{
			std::lock_guard<std::mutex> lock(m_mutex);
			m_iFlags |= _iFlags;
		}

		bool LogManager::IsFlagActive(uint32 _iFlag) const
		{
			return (m_iFlags & _iFlag) != 0;
		}
	}
}